package com.mrper.filedialog.data.adapter

import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
import com.mrper.filedialog.utils.img.ImageLoader


/**
 * Created by mrper on 17-3-14.
 *
 * 基类数据绑定器
 *
 * @param context 上下文对象
 * @param layoutId item布局ID
 * @param dataSource 数据源
 */
abstract class BaseListAdapter<E : Any> @JvmOverloads constructor(
    val context: Context,
    @LayoutRes private val layoutId: Int,
    var dataSource: MutableList<E>? = mutableListOf()
) : BaseAdapter() {

    /**  获取适配器数据源  **/
    fun getAdapterDataSource(): MutableList<E>? = dataSource

    /**
     * 添加数据
     *
     * @param e 数据项
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun add(e: E, isRefresh: Boolean = false) {
        dataSource?.add(e)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 添加数据
     *
     * @param e 数据项
     * @param index 要插入的索引位置
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun add(e: E, index: Int, isRefresh: Boolean = false) {
        dataSource?.add(index, e)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 添加多个数据
     *
     * @param elements 数据项集合
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun add(elements: MutableList<E>, isRefresh: Boolean = false) {
        dataSource?.addAll(elements)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 添加数据集合
     * @param es 数据集合
     * @param isRefresh 是否刷新
     */
    @Synchronized
    @JvmOverloads
    fun add(vararg es: E, isRefresh: Boolean = false) {
        dataSource?.addAll(es.toMutableList())
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 删除数据项
     *
     * @param e 要删除的数据项
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun remove(e: E, isRefresh: Boolean = false) {
        dataSource?.remove(e)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 删除某一索引位置的数据
     *
     * @param index 数据索引位置
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun remove(index: Int, isRefresh: Boolean = false) {
        dataSource?.removeAt(index)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 删除数据集合
     *
     * @param elements 数据集合
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun remove(elements: MutableList<E>, isRefresh: Boolean = false) {
        dataSource?.removeAll(elements)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 更新某处的数据
     *
     * @param index 要更新的数据的索引
     * @param e 数据内容
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun update(index: Int, e: E, isRefresh: Boolean = false) {
        dataSource?.set(index, e)
        if (isRefresh)
            notifyDataSetChanged()
    }

    /**
     * 清空所有数据
     *
     * @param isRefresh 是否刷新数据，默认为false
     */
    @Synchronized
    @JvmOverloads
    fun clear(isRefresh: Boolean = false) {
        dataSource?.clear()
        if (isRefresh)
            notifyDataSetChanged()
    }

    override fun getCount(): Int = dataSource?.size ?: 0

    override fun getItem(position: Int): Any? = dataSource?.get(position)

    override fun getItemId(position: Int): Long = position.toLong()

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
        val viewHolder = ViewHolder.getInstance(context, position, convertView, parent, layoutId)
        bindValues(viewHolder, position, dataSource?.get(position)!!)
        return viewHolder.convertView
    }

    /**
     * 绑定数据
     *
     * @param holder
     * @param position 数据索引
     * @param itemData 数据项
     */
    abstract fun bindValues(holder: ViewHolder, position: Int, itemData: E)

    /**
     * ViewHolder对象
     *
     * @param context 上下文对象
     * @param position 数据索引
     * @param convertView itemView
     * @param parent Group-Root
     * @param layoutId item布局ID
     */
    @Suppress("unused")
    class ViewHolder(
        val context: Context,
        val position: Int,
        convertView: View?,
        parent: ViewGroup?,
        @LayoutRes val layoutId: Int
    ) {

        companion object {

            /**
             * 获取ViewHolder实例
             *
             * @param context 上下文对象
             * @param position 数据索引
             * @param convertView itemView对象
             * @param parent RootParent
             * @param layoutId Item布局ID
             */
            @JvmStatic
            fun getInstance(
                context: Context,
                position: Int,
                convertView: View?,
                parent: ViewGroup?,
                layoutId: Int
            ): ViewHolder = if (convertView != null)
                convertView.tag as ViewHolder
            else
                ViewHolder(context, position, convertView, parent, layoutId)
        }

        var convertView: View?
            private set

        init {
            this.convertView = convertView ?: View.inflate(context, layoutId, null)
            this.convertView?.tag = this
        }

        /**
         * 根据ID获取控件对象
         *
         * @param id 控件ID
         */
        @Suppress("UNCHECKED_CAST")
        fun <T : View> getViewById(@IdRes id: Int): T? {
            val result: View? = convertView?.findViewById(id)
            return result as? T?
        }

        /**
         * 设置文本控件的文本
         *
         * @param id 控件ID
         * @param text 文本内容
         */
        fun setText(@IdRes id: Int, text: CharSequence): ViewHolder {
            getViewById<TextView>(id)?.text = text
            return this
        }

        /**
         * 设置文本控件的文本
         *
         * @param id  控件ID
         * @param textId 数据String ID
         */
        fun setText(@IdRes id: Int, @StringRes textId: Int): ViewHolder {
            setText(id, context.getString(textId))
            return this
        }

        /**
         * 设置控件图片
         *
         * @param id 图片控件ID
         * @param url 图片数据URL对象
         */
        fun setImage(@IdRes id: Int, url: Any): ViewHolder {
            val imageViewInstance = getViewById<ImageView>(id)
            imageViewInstance?.let {
                ImageLoader.displayImage(imageViewInstance, uri = url, target = imageViewInstance)
            }
            return this
        }

    }

}